home *** CD-ROM | disk | FTP | other *** search
/ Macworld Expo - Develope…Central & Net Innovations / Developer Central and Net Innovators (MacWorld Expo) (January 1999).iso / Developer Central / Metrowerks CodeWarrior / CodeWarrior Pro 4 Release Notes / Libraries Notes / MSL Technical Notes / DebugNew.doc next >
Encoding:
Text File  |  1998-08-21  |  12.5 KB  |  285 lines  |  [TEXT/CWIE]

  1. Documentation for DebugNew.cp
  2. =============================
  3.  
  4. Date:        August 21, 1998 
  5. Author:      Dan Podwall
  6. Maintenance: John C. Daub
  7.  
  8. Change Notes:
  9. `````````````
  10.  
  11. Pro 4 release:
  12.     - Support for array new and array delete added (MW03205, MW06521).
  13.       This also added a check to ensure calls to new/delete and
  14.       new[]/delete[] match. If you have a custom error handler, you
  15.       may wish to update it to support dbgnewMismatchedNewDelete
  16.       and the updated text for dbgnewBadHeader.
  17.       
  18.       This support also attempts to contend with possible compiler-inserted
  19.       padding (as is done by MW C/C++ for arrays of C++ objects allocated
  20.       via new[]).
  21.       
  22.       Furthermore, any calls to DebugNewDoAllocate and DebugNewDoFree
  23.       will probably need to be updated. Both functions now accept a
  24.       bool is_array as argument (to support the above functionality).
  25.  
  26.     - Updated references to runtime libraries in docs (MW01208)
  27.     
  28.     - Fixed a bug in DebugNewReportLeaks that could case an incorrect
  29.       number of leaks to be reported (MW02460, MW02750)
  30.     
  31.     - DebugNew.cp should now compile cleanly and generate no warnings
  32.       (MW05838). Implicit arithmetic conversions may still exist, however.
  33.       
  34.       
  35. CW/10 release:
  36.     - Added support for class-specific operator new/delete
  37.     
  38.     - With leak-checking enabled, the block list is kept
  39.       in a hash table instead of a linked list to speed up
  40.       searching for blocks and reduce the perfomance impact
  41.       of leak checking.
  42.       
  43.     - Added DebugNewForgetLeaks(). Use this to eliminate
  44.       extraneous leak reports due to memory that is allocated
  45.       at program startup and never freed. Helpful with PowerPlant
  46.       applications.
  47.       
  48.     - Added DEBUG_NEW_IMPLEMENTATION so you can specify the
  49.       source file implementing global operators new/delete
  50.       without having to modify this file. Typical usage is
  51.       to define this macro in your prefix file, e.g.
  52.       #define DEBUG_NEW_IMPLEMENTATION "MyNewAndDelete.cp"
  53.       
  54.     - Added DEBUG_NEW_NO_GLOBAL_OPERATORS macro so you can prevent
  55.       DebugNew from defining global operators new/delete. Define
  56.       this if you need to use your own global new/delete operators
  57.       but still want to use DebugNew. These operators should call
  58.       DebugNewDoAllocate and DebugNewDoFree when DebugNew is active.
  59.       If you use leak checking, then you must also implement
  60.       operator new(size_t size, const char*, int). Use the
  61.       file New.cp in the MacOS Support:Libraries:Runtime:Common Sources:
  62.       folder as an example.
  63.       
  64.     - DebugNewReportLeaks() returns the number of leaks found.
  65.     
  66.     - Updated for CW10 runtime libraries.
  67.  
  68. CW/6 release:
  69.     - Modifed source to work with new C++ runtime library.
  70.     - Updated documentation
  71.  
  72. CW/4 release: 
  73.     - Fixed compiler warnings
  74.     - Added gDebugNewFlags, dnDontFreeBlocks, with associated support
  75.       code and diagnostic messages. See the "Changing runtime behavior"
  76.       section for more information.
  77.     - Removed obsolete array support, will re-implement when we 
  78.       have operator new[] and operator delete[].
  79.     - Changed default error reporting to DebugStr68k, so the same method
  80.       is used on both 68K and PowerPC. (DebugStr68k always passes messages
  81.       to Macsbug on PPC, DebugStr doesn't.)
  82.   
  83. Introduction
  84. ````````````
  85.     The DebugNew package provides a debugging layer over the standard operators
  86.     new, new[], delete, and delete[]. It can help to diagnose common errors
  87.     associated with dynamically allocated memory.
  88.     
  89.     It provides the following services:
  90.       
  91.     - Zaps newly allocated and free blocks with bad values to detect uses
  92.       of uninitialized or deallocated memory.
  93.       
  94.     - Addresses of blocks to be freed are checked to see if they are within
  95.       the application heap.
  96.  
  97.     - Tags allocated blocks to detect double freeing, freeing unknown
  98.       blocks, and overwriting past the end of a block.
  99.       
  100.     - A counter is incremented on allocations and decremented on frees.
  101.       A warning is generated if there are more frees than allocs. You 
  102.       can inspect the counter as a crude check to see if any memory has
  103.       leaked.
  104.       
  105.     - Tracks the current number of bytes allocated via operator new
  106.       and the maximum number of bytes ever allocated. Useful for
  107.       tuning memory management and determining a good size memory
  108.       pool to pre-allocate at program startup.
  109.       
  110.     - Optionally tracks memory allocations and can report memory leaks.
  111.       The source file and line is tracked for each allocation, and
  112.       the list of allocated blocks can be dumped to a text file. Full use
  113.       of this feature requires using the macro NEW instead of new in your
  114.       source code.
  115.       
  116.     - Optionally zaps and prevents reuse of freed blocks. This can help
  117.       catch uses of dangling pointers.
  118.             
  119. Using DebugNew, basic level
  120. ```````````````````````````
  121.     To get the basic level of checking, all you need to do is add it your project.
  122.     The DebugNew source is located inside the "MacOS Support:Libraries:DebugNew:"
  123.     folder. Just go to that folder and add DebugNew.cp to your project. Make sure
  124.     you do not have New.cp in your project -- you should just have MSL Runtime68K.lib
  125.     for 68K programs or MSL RuntimePPC.lib for PPC programs.
  126.     
  127.     At link time, you will get some linker warnings because DebugNew is overriding 
  128.     some  runtime library routines. You can get rid of this by enabling "Supress 
  129.     warning messages" under the linker preferences.
  130.         
  131.     Doing this gives you all the above features except for full leak checking.
  132.     
  133. Enabling memory leak checking
  134. `````````````````````````````
  135.     To enable full leak checking, you must include DebugNew.h in every source
  136.     file you want checked, or just make sure your project prefix includes it.
  137.     Insert the line "#define DEBUG_NEW    2" either in your prefix, or add it
  138.     to the DebugNew.h header.
  139.                 
  140.     Every usage of global operator new must be changed to use the macro NEW.
  141.     For example, change:
  142.     
  143.         MyObject* obj = new MyObject;
  144.     
  145.     to:
  146.     
  147.           MyObject* obj = NEW MyObject;
  148.       
  149.     It is possible to "#define new NEW" in your prefix to avoid inserting
  150.     NEW throughout your code. However this can be dangerous as the preprocessor
  151.     is smart but not intelligent and could replace something you do not want
  152.     replaced. It is best to replace each use of the global operator new to
  153.     use the macro NEW. Use the "#define new NEW" trick at your own risk.
  154.     
  155.     When leak checking is enabled, NEW expands to new(__FILE__,__LINE__). This
  156.     is an overloaded form of operator new. When leak checking is disabled,
  157.     NEW simply expands to new. Again, when leak checking is off, this
  158.     expands to the normal operator new, so you can leave this in your
  159.     final code and there is absolutely no overhead.
  160.     
  161.     If leak checking is enabled and the standard new is called, the block is
  162.     still tracked, but the leak report will be missing source file and line
  163.     information for that block. So, you could enable leak checking without
  164.     using NEW. However, the information you get won't be useful enough to
  165.     warrant the overhead.
  166.     
  167.     The NEW macro (as of the Pro 4 revision of DebugNew) can be used when
  168.     allocating C++ arrays. In fact, DebugNew does attempt to catch use
  169.     of delete[] on a new block, or delete on a new[] block. One caveat for
  170.     this support is that the compiler may insert its own header on the
  171.     pointer (in addition to the DebugNew BlockHeader). This compiler header
  172.     is used to store the size of an array element and the number of array
  173.     elements (used internally by the compiler and runtimes. See the Runtime
  174.     Common source NMWException.cp for more details). DebugNew attempts to
  175.     contend with this potential for compiler padding (GetHeader()), but it
  176.     might not be 100% fool-proof (see the comments in GetHeader() for
  177.     more details). If you fail for this reason, it may be wise to examine
  178.     the memory just before your pointer to see what's there, coupled with
  179.     an examination of how your compiler/runtime work for array allocations.
  180.     
  181.     Nothing special needs to be done when freeing objects. Just use the normal
  182.     operator delete (or delete[]).
  183.  
  184.     Since the leak report uses stdio to write a text file, you must include
  185.     the ANSI C library in your project.
  186.     
  187. Disabling DebugNew
  188. ``````````````````
  189.     If you are using the basic level of checking, and don't use the NEW macro,
  190.     just remove DebugNew.cp from your project. Or, you can just put 
  191.     "#define DEBUG_NEW 0" in your prefix. The result is the same.
  192.     
  193.     If you are using NEW, you must continue to include DebugNew.h in your source.
  194.     Just put "#define DEBUG_NEW 0" in your prefix or at the top of DebugNew.h.
  195.     
  196. Error Reporting
  197. ```````````````
  198.     Errors are reported in two ways. When a validation check occurs at runtime,
  199.     an error handler routine is called. The default routine just issues a DebugStr()
  200.     call with a diagnostic message. If you prefer different behavior, you can
  201.     provide your own error handler by calling DebugNewSetErrorHandler(). Validation
  202.     errors occur when operator delete is called, or when your code calls 
  203.     DebugNewValidatePtr() or DebugNewValidateAllBlocks().
  204.     
  205.     Memory leaks are reported via the file "leaks.log". This file is written to the
  206.     application's directory whenever DebugNewReportLeaks() is called. One possible
  207.     approach is to call it as the last statement in main(), before your application
  208.     exits.
  209.     
  210. Changing runtime behavior
  211. `````````````````````````
  212.  
  213. The behavior controlled by the DEBUG_NEW macro (off, basic, leaks) is determined
  214. at compile time, since appropriate support must be compiled into your code, or
  215. removed from your code when disabling DebugNew.
  216.  
  217. When DebugNew is enabled, the gDebugNewFlags global contains flags that you
  218. can set to change DebugNew's behavior. By default, gDebugNewFlags is set to
  219. dnCheckBlocksInApplZone, meaning by default all valid blocks must be within
  220. the application zone. You can set the dnDontFreeBlocks flag (or any flag)
  221. as follows:
  222.  
  223.     gDebugNewFlags |= dnDontFreeBlocks;  // set flag
  224.     gDebugNewFlags &= ~dnDontFreeBlocks; // clear flag
  225.     
  226. When the dnDontFreeBlocks flag is set, operator delete will not actually
  227. release memory, but it will mark the block as freed and zap the contents. Keep
  228. in mind that in the normal situation, freed memory may be reallocated on
  229. subsequent calls to operator new. So when you have a dangling pointer,
  230. it may point either to a free block or to an allocated block that
  231. doesn't have the data you think it does. Subtle and hard to find bugs
  232. may result.
  233.  
  234. With only basic checking enabled, setting dnDontFreeBlocks may increase
  235. the likelihood that you can catch a use of a dangling pointer, since
  236. you will see bad data quickly, and DebugNewValidatePtr will give an
  237. error. This is especially true if you use a dangling pointer to fetch
  238. another pointer.
  239.     
  240. The dnDontFreeBlocks flag is most useful when leak checking is also 
  241. enabled. In that case, freed blocks are also maintained on the block list.
  242. If your program writes through a dangling pointer, the next call to 
  243. DebugNewValidateAllBlocks will find and signal the error.
  244.  
  245. Note that the dnDontFreeBlocks has a major impact on memory usage.
  246. Since memory is not freed, your memory requirements will go up while
  247. the flag is set. As with leak checking, the intent is that you would
  248. only use this feature during intense debugging sessions when that
  249. is not an issue.
  250.     
  251. When the dnCheckBlocksInApplZone flag is set, any action that checks
  252. a block's status (just about anything in DebugNew will do this) will first
  253. check to ensure the block is within the application's heap. If it is
  254. not, it will return a BlockStatus_t of blockPtrOutOfRange.
  255.     
  256. Limitations
  257. ```````````
  258.     - By default, DebugNew only works for the global operator new. However,
  259.       if your class-specific operator new calls the global operator new, then
  260.       those allocations will be tracked.
  261.  
  262.     - DebugNew does not attempt to do anything when an allocation fails.
  263.       That is what set_new_handler() is for.
  264.  
  265. Overhead
  266. ````````
  267. Both the basic checking and memory leak checking add overhead to your program. You
  268. generally would only enable it for internal testing.
  269.  
  270. Basic checking adds 12 bytes to each allocated block, and slows down each new/delete
  271. only slightly.
  272.  
  273. Leak checking increases the per block overhead to 24 bytes. There is also
  274. the overhead of finding and removing each block from the block list
  275. when it is deleted. The memory and time hit will be noticable on moderate to 
  276. large programs. Leak testing should generally only be enabled periodically to 
  277. clean up leaks, and then turned off again.
  278.  
  279. Any use of padding by the compiler (e.g. in an array of C++ objects allocated
  280. via new[]) does affect the stored and possibly reported size of a block.
  281. DebugNewGetPtrSize() compensates for padding, so it should always return the
  282. proper size of the block. When generating the leaks.log however, the size
  283. of the pointer plus any compiler padding is reported. But to help you identify
  284. and compensate, the leaks.log should also report the size of the compiler
  285. padding, if any.